﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace ConquerServer_Basic
{
    public class Database
    {
        public static string DatabasePath = (Application.StartupPath + @"\Database");

        public static bool IsValidAccount(AuthClient Client, ref uint UID)
        {
            UID = 0;
            IniFile rdr = new IniFile(DatabasePath + @"\Accounts\" + Client.Username + ".ini");
            if (rdr.ReadString("Account", "Username", "", 16).Equals(Client.Username, StringComparison.CurrentCultureIgnoreCase))
            {
                string Password = rdr.ReadString("Account", "Password", "", 40);
                if (Password == "")
                {
                    Password = Client.Password;
                    rdr.Write("Account", "Password", Password);
                }
                if (Password.Equals(Client.Password, StringComparison.CurrentCultureIgnoreCase))
                {
                    UID = rdr.ReadUInt32("Character", "UID", 0);
                }
            }
            return (UID != 0);
        }
        public static void GetStats(GameClient Client)
        {
            string Job;
            if (Client.Job >= 10 && Client.Job <= 15)
                Job = "Trojan";
            else if (Client.Job >= 20 && Client.Job <= 25)
                Job = "Warrior";
            else if (Client.Job >= 40 && Client.Job <= 45)
                Job = "Archer";
            else
                Job = "Taoist";
            string Lvl = Math.Min(Client.Entity.Level, (ushort)120).ToString();
            IniFile rdr = new IniFile(Database.DatabasePath + @"\Misc\" + Job + ".ini");

            Client.Spirit = rdr.ReadUInt16(Lvl, "Spirit", 0);
            Client.Strength = rdr.ReadUInt16(Lvl, "Strength", 0);
            Client.Agility = rdr.ReadUInt16(Lvl, "Agility", 0);
            Client.Vitality = rdr.ReadUInt16(Lvl, "Vitality", 0);
            if (Client.Entity.Reborn == 0)
            {
                Client.StatPoints = 0;
            }
            else
            {
                Client.StatPoints = (ushort)(Client.Spirit + Client.Strength + Client.Agility + Client.Vitality);
                Client.Spirit = Client.Strength = Client.Agility = Client.Vitality = 0;
            }
        }

        private static void LoadInventory(GameClient Client)
        {
            IniFile rdr = new IniFile(DatabasePath + @"\Inventory\" + Client.Username + ".ini");
            sbyte count = rdr.ReadSByte("Inventory", "Count", 0);
            for (sbyte i = 0; i < count; i++)
            {
                ItemDataPacket LoadedItem; 
                if (ItemDataPacket.Parse(rdr.ReadString("Inventory", "Items[" + i.ToString() + "]", String.Empty), out LoadedItem))
                {
                    LoadedItem.UID = ItemDataPacket.NextItemUID;
                    Client.AddInventory(LoadedItem);
                }
            }
        }
        private static void SaveInventory(GameClient Client)
        {
            IniFile wrtr = new IniFile(DatabasePath + @"\Inventory\" + Client.Username + ".ini");
            // I use a foreach loop because the Inventory
            // variables length can change at any time technically
            // seeing as it's in sync with the dictionary, but not
            // neccicarly with the function calling it
            // this is rare -- but I've had it happen.
            sbyte i = 0;
            foreach (IConquerItem Item in Client.Inventory)
            {
                wrtr.Write("Inventory", "Item[" + i.ToString() + "]", Item.ToString());
            }
            wrtr.Write("Inventory", "Count", i.ToString());
        }

        public static void LoadItemStats(GameClient Client, IConquerItem Item)
        {
            IniFile rdr;
            StanderdItemStats standerd = new StanderdItemStats(Item.ID, out rdr);

            Client.Entity.Defence += standerd.PhysicalDefence;
            Client.Entity.MDefence += standerd.MDefence;
            Client.Entity.Dodge += standerd.Dodge;

            Client.BaseMagicAttack += standerd.MAttack;
            Client.ItemHP += standerd.HP;
            Client.ItemMP += standerd.MP;

            if (Item.Position == ItemPosition.Right)
            {
                Client.AttackRange += standerd.AttackRange;
            }
            if (Item.Position == ItemPosition.Left)
            {
                Client.BaseMinAttack += (uint)(standerd.MinAttack * 0.5F);
                Client.BaseMaxAttack += (uint)(standerd.MaxAttack * 0.5F);
            }
            else
            {
                Client.BaseMinAttack += standerd.MinAttack;
                Client.BaseMaxAttack += standerd.MaxAttack;
            }

            if (Item.Plus != 0)
            {
                PlusItemStats plus = new PlusItemStats(Item.ID, Item.Plus, rdr);
                Client.BaseMinAttack += plus.MinAttack;
                Client.BaseMaxAttack += plus.MaxAttack;
                Client.BaseMagicAttack += plus.MAttack;
                Client.Entity.Defence += plus.PhysicalDefence;
                Client.Entity.PlusMDefence += plus.PlusMDefence;
                Client.ItemHP += plus.HP;
            }
            if (Item.Position != ItemPosition.Garment && // Ignore these stats on these slots
                Item.Position != ItemPosition.Bottle)
            {
                Client.ItemHP += Item.Enchant;
                Client.BlessPercent += Item.Bless;
                //GemAlgorithm(Client, Item->SocketOne, Item->SocketTwo, true);
            }
        }
        public static void UnloadItemStats(GameClient Client, IConquerItem Item)
        {
            IniFile rdr;
            StanderdItemStats standerd = new StanderdItemStats(Item.ID, out rdr);

            Client.Entity.Defence -= standerd.PhysicalDefence;
            Client.Entity.MDefence -= standerd.MDefence;
            Client.Entity.Dodge -= standerd.Dodge;

            Client.BaseMagicAttack -= standerd.MAttack;
            Client.ItemHP -= standerd.HP;
            Client.ItemMP -= standerd.MP;

            if (Item.Position == ItemPosition.Right)
            {
                Client.AttackRange = 0;
            }
            if (Item.Position == ItemPosition.Left)
            {
                Client.BaseMinAttack -= (uint)(standerd.MinAttack * 0.5F);
                Client.BaseMaxAttack -= (uint)(standerd.MaxAttack * 0.5F);
            }
            else
            {
                Client.BaseMinAttack -= standerd.MinAttack;
                Client.BaseMaxAttack -= standerd.MaxAttack;
            }

            if (Item.Plus != 0)
            {
                PlusItemStats plus = new PlusItemStats(Item.ID, Item.Plus, rdr);
                Client.BaseMinAttack -= plus.MinAttack;
                Client.BaseMaxAttack -= plus.MaxAttack;
                Client.BaseMagicAttack -= plus.MAttack;
                Client.Entity.Defence -= plus.PhysicalDefence;
                Client.Entity.PlusMDefence -= plus.PlusMDefence;
                Client.ItemHP -= plus.HP;
            }
            if (Item.Position != ItemPosition.Garment && // Ignore these stats on these slots
                Item.Position != ItemPosition.Bottle)
            {
                Client.ItemHP -= Item.Enchant;
                Client.BlessPercent -= Item.Bless;
                //GemAlgorithm(Client, Item->SocketOne, Item->SocketTwo, false);
            }
        }

        public static bool LoadCharacter(GameClient Client)
        {
            IniFile rdr = new IniFile(DatabasePath + @"\Accounts\" + Client.Username + ".ini");
            bool res = false;
            Client.Entity.UID = rdr.ReadUInt32("Character", "UID", 0);
            if (Client.Entity.UID == Client.Identifier)
            {
                res = true;
                Client.Entity.Name = rdr.ReadString("Character", "Name", "INVALID_NAME", 16);
                Client.Money = rdr.ReadInt32("Character", "Money", 0);
                Client.Entity.Model = rdr.ReadUInt32("Character", "Model", 1003);
                Client.ConquerPoints = rdr.ReadInt32("Character", "ConquerPoints", 0);
                Client.Job = rdr.ReadByte("Character", "Job", 10);
                Client.Spouse = "None";
                Client.Entity.Reborn = rdr.ReadByte("Character", "RebornCount", 0);
                Client.Entity.Level = (byte)rdr.ReadInt32("Character", "Level", 1);
                if (Client.Entity.Reborn > 0)
                {
                    Client.Strength = rdr.ReadUInt16("Character", "Strength", 1);
                    Client.Agility = rdr.ReadUInt16("Character", "Agility", 1);
                    Client.Spirit = rdr.ReadUInt16("Character", "Spirit", 1);
                    Client.Vitality = rdr.ReadUInt16("Character", "Vitality", 1);
                }
                else
                {
                    GetStats(Client);
                }
                Client.Entity.Hitpoints = rdr.ReadInt32("Character", "Hitpoints", 0);
                Client.Mana = rdr.ReadUInt16("Character", "Mana", 0);
                Client.Entity.HairStyle = rdr.ReadUInt16("Character", "Hairstyle", 421);
                Client.Entity.MapID = rdr.ReadUInt16("Character", "MapID", 1002);
                Client.Entity.X = rdr.ReadUInt16("Character", "X", 400);
                Client.Entity.Y = rdr.ReadUInt16("Character", "Y", 400);
            }
            LoadInventory(Client);

            return res;
        }
        public static void SaveCharacter(GameClient Client)
        {
            IniFile wrtr = new IniFile(DatabasePath + @"\Accounts\" + Client.Username + ".ini");
            wrtr.Write("Character", "Name", Client.Entity.Name);
            wrtr.Write("Character", "Money", Client.Money);
            wrtr.Write("Character", "Model", Client.Entity.Model);
            wrtr.Write("Character", "ConquerPoints", Client.ConquerPoints);
            wrtr.Write("Character", "Job", Client.Job);
            wrtr.Write("Character", "Strength", Client.Strength);
            wrtr.Write("Character", "Agility", Client.Agility);
            wrtr.Write("Character", "Spirit", Client.Spirit);
            wrtr.Write("Character", "Vitality", Client.Vitality);
            wrtr.Write("Character", "Hitpoints", Client.Entity.Hitpoints);
            wrtr.Write("Character", "Mana", Client.Mana);
            wrtr.Write("Character", "Level", Client.Entity.Level);
            wrtr.Write("Character", "Hairstyle", Client.Entity.HairStyle);
            wrtr.Write("Character", "MapID", Client.Entity.MapID);
            wrtr.Write("Character", "X", Client.Entity.X);
            wrtr.Write("Character", "Y", Client.Entity.Y);
            wrtr.Write("Character", "RebornCount", Client.Entity.Reborn);

            SaveCharacter(Client);
        }
     }
}
